/**
 * @file MySQLClient.cc
 * @brief MySQL数据库客户端类的实现
 */

#include "MySQLClient.hpp"
#include <iostream>
#include <mysql/mysql.h>
#include <string>

using std::string;
using std::cout;
using std::endl;
using std::to_string;

namespace wd
{
// 构造函数：初始化MySQL连接
MySQLClient::MySQLClient()
{
    MYSQL * pconn = mysql_init(&_conn);
    if(!pconn) {
        MyLogger::getInstance().dbError( "mysqlclient init error") ;
    }
}

// 析构函数：关闭MySQL连接
MySQLClient::~MySQLClient()
{
    mysql_close(&_conn);
}

// 连接到MySQL数据库
bool MySQLClient::connect(const string & host,
                          unsigned short port,
                          const string & user,
                          const string & passwd,
                          const string & db)
{
    MYSQL * pconn = mysql_real_connect(&_conn,
                                       host.c_str(),
                                       user.c_str(),
                                       passwd.c_str(),
                                       db.c_str(),
                                       port,
                                       nullptr,
                                       0);
    if(!pconn) {
        MyLogger::getInstance().dbError("Mysql connect error!") ;
        printf("(%d, %s)\n", mysql_errno(&_conn), mysql_error(&_conn));
        return false;
    } else
        return true;
}

//执行INSERT/UPDATE/DELTE语句
bool MySQLClient::writeOperationQuery(const string & sql)
{
    int ret = mysql_real_query(&_conn, sql.c_str(), sql.size());
    if(ret != 0) {
        string msg = "("+ to_string(mysql_errno(&_conn))+"," + mysql_error(&_conn) + ")";
        MyLogger::getInstance().dbError(sql +  " : "+msg) ;
        printf("(%d, %s)\n", mysql_errno(&_conn), mysql_error(&_conn));
        return false;
    } else {

        char buffer[100] = {0};
        sprintf(buffer,"Query OK, %ld row(s) affected.",mysql_affected_rows(&_conn));
        MyLogger::getInstance().dbInfo(sql + " : "+buffer) ;

        printf("Query OK, %ld row(s) affected.\n",
               mysql_affected_rows(&_conn));
        return true;
    }
}
//执行select语句的查询
vector<vector<string>> MySQLClient::readOperationQuery(const string & sql)
{
    MyLogger::getInstance().dbInfo("Execute SELECT query: " + sql);

    int ret = mysql_real_query(&_conn, sql.c_str(), sql.size());
    if(ret != 0) {
        // 查询执行失败：记录错误日志（错误码+错误信息）
        string msg = "(" + to_string(mysql_errno(&_conn)) + "," + mysql_error(&_conn) + ")";
        MyLogger::getInstance().dbError("SELECT query failed: " + sql + " : " + msg);

        printf("(%d, %s)\n", mysql_errno(&_conn), mysql_error(&_conn));
        return vector<vector<string>>();
    }
    vector<vector<string>> queryRes;;
    MYSQL_RES * res = mysql_store_result(&_conn);
    if(!res) {
        // 获取结果集失败：记录错误日志
        string msg = "(" + to_string(mysql_errno(&_conn)) + "," + mysql_error(&_conn) + ")";
        MyLogger::getInstance().dbError("Get result set failed: " + sql + " : " + msg);

        printf("(%d, %s)\n", mysql_errno(&_conn), mysql_error(&_conn));
        return vector<vector<string>>();
    }
    //有结果集的情况
    int rows = mysql_num_rows(res);
    if(rows == 0) {
        return vector<vector<string>>();
    }

    queryRes.reserve(rows + 1);
    int cols = mysql_num_fields(res);

    MyLogger::getInstance().dbInfo("SELECT query succeeded: " + sql 
        + " | rows: " + to_string(rows) + ", cols: " + to_string(cols));

    printf("rows: %d, cols: %d\n", rows, cols);
    MYSQL_FIELD * filed = nullptr;
    vector<string> fileds;
    while((filed = mysql_fetch_field(res)) != nullptr) {
        fileds.push_back(filed->name);
    }
    queryRes.push_back(std::move(fileds));//转移到容器中
    MYSQL_ROW row;
    while((row = mysql_fetch_row(res)) != nullptr) {
        vector<string> tmp;
        tmp.reserve(cols);
        for(int i = 0; i < cols; ++i) {
            if(row[i] != NULL) {
                tmp.push_back(string(row[i]));
            } else {
                tmp.push_back(string());
            }
            //cout << "i:" << i << endl;
        }
        //获取一行数据，加入到结果集中
        queryRes.push_back(tmp);
    }
    mysql_free_result(res);
    return queryRes;
}
//对结果集进行打印操作
void MySQLClient::dump(const vector<vector<string>> & res)
{
    cout << "result set has " << res.size() << " row(s)" << endl;

    for(auto & vec : res) {
        for(auto & filed : vec) {
            cout << filed << "\t";
        }
        cout << endl;
    }
    cout << endl;
}
string MySQLClient::getSetting(const string & name){
    /* string sql = "select setting from shms_user where name = " +string("'")+name + "'"; */
    /* int ret = mysql_real_query(&_conn, sql.c_str(), sql.size()); */
    
    /* if(ret != 0) { */
    /*     // 查询执行失败：记录错误日志（错误码+错误信息） */
    /*     string msg = "(" + to_string(mysql_errno(&_conn)) + "," + mysql_error(&_conn) + ")"; */
    /*     MyLogger::getInstance().dbError("SELECT query failed: " + sql + " : " + msg); */

    /*     printf("(%d, %s)\n", mysql_errno(&_conn), mysql_error(&_conn)); */
    /*     return ""; */
    /* } */
    /* MYSQL_RES * res = mysql_store_result(&_conn); */
    /* if(!res) { */
    /*     // 获取结果失败：记录错误日志 */
    /*     string msg = "(" + to_string(mysql_errno(&_conn)) + "," + mysql_error(&_conn) + ")"; */
    /*     MyLogger::getInstance().dbError("Get result set failed: " + sql + " : " + msg); */
    /*     printf("(%d, %s)\n", mysql_errno(&_conn), mysql_error(&_conn)); */
    /*     return ""; */
    /* } */

    /* int rows = mysql_num_rows(res); */
    /* if(rows == 0) { */
    /*     MyLogger::getInstance().dbInfo("Get result ( " + sql + " ): null" ); */
    /*     return ""; */
    /* } */
    /* MYSQL_ROW row; */
    /* row = mysql_fetch_row(res); */
    /* mysql_free_result(res); */
    /* string result = row[0]; */
    /* MyLogger::getInstance().dbInfo("Get result ( " + sql + " ): "+result ); */
    /* return result; */
    string sql = "select setting from shms_user where name = " +string("'")+name + "'";
    vector<vector<string>> res = readOperationQuery(sql);
    if(res.size()== 0){
        MyLogger::getInstance().dbInfo("Get result ( " + sql + " ): null" );
        return "";
    }
    string setting = res[1][0];

    MyLogger::getInstance().dbInfo("Get result ( " + sql + " ): "+setting );
    return setting;
}
string MySQLClient::getEncrypt(const string & setting){
    /* string sql = "select encrypt from shms_user where setting = " +string("'")+setting + "'"; */
    /* int ret = mysql_real_query(&_conn, sql.c_str(), sql.size()); */
    
    /* if(ret != 0) { */
    /*     // 查询执行失败：记录错误日志（错误码+错误信息） */
    /*     string msg = "(" + to_string(mysql_errno(&_conn)) + "," + mysql_error(&_conn) + ")"; */
    /*     MyLogger::getInstance().dbError("SELECT query failed: " + sql + " : " + msg); */

    /*     printf("(%d, %s)\n", mysql_errno(&_conn), mysql_error(&_conn)); */
    /*     return ""; */
    /* } */
    /* MYSQL_RES * res = mysql_store_result(&_conn); */
    /* if(!res) { */
    /*     // 获取结果失败：记录错误日志 */
    /*     string msg = "(" + to_string(mysql_errno(&_conn)) + "," + mysql_error(&_conn) + ")"; */
    /*     MyLogger::getInstance().dbError("Get result set failed: " + sql + " : " + msg); */
    /*     printf("(%d, %s)\n", mysql_errno(&_conn), mysql_error(&_conn)); */
    /*     return ""; */
    /* } */

    /* int rows = mysql_num_rows(res); */
    /* if(rows == 0) { */
    /*     MyLogger::getInstance().dbInfo("Get result ( " + sql + " ): null" ); */
    /*     return ""; */
    /* } */
    /* MYSQL_ROW row; */
    /* row = mysql_fetch_row(res); */
    /* mysql_free_result(res); */
    /* string result = row[0]; */
    /* MyLogger::getInstance().dbInfo("Get result ( " + sql + " ): "+result ); */
    /* return result; */
    
    string sql = "select encrypt from shms_user where setting = " +string("'")+setting + "'";
    vector<vector<string>> res = readOperationQuery(sql);
    if(res.size()== 0){
        MyLogger::getInstance().dbInfo("Get result ( " + sql + " ): null" );
        return "";
    }
    string encrypt = res[1][0];

    MyLogger::getInstance().dbInfo("Get result ( " + sql + " ): "+encrypt );
    return encrypt;
}
bool MySQLClient::hasName(const string &name){
    string sql = "select setting from shms_user where name = " +string("'")+name + "'";
    vector<vector<string>> result = readOperationQuery(sql);
    return result.size() != 0;
}


}//end of namespace wd


